Load the datasets

library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
-- Attaching packages -------------------------------------------------------------------------- tidyverse 1.3.1 --
v ggplot2 3.3.5     v purrr   0.3.4
v tibble  3.1.2     v dplyr   1.0.7
v tidyr   1.1.3     v stringr 1.4.0
v readr   2.0.0     v forcats 0.5.1
-- Conflicts ----------------------------------------------------------------------------- tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(janitor)

Attaching package: ‘janitor’

The following objects are masked from ‘package:stats’:

    chisq.test, fisher.test
library(here)
here() starts at E:/Prathiba_Course/_codeclan/my_projects/phs_covid/analysis
library(ggplot2)
library(lubridate)

Attaching package: ‘lubridate’

The following objects are masked from ‘package:base’:

    date, intersect, setdiff, union
library(plotly)
Warning: package ‘plotly’ was built under R version 4.1.1
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
Registered S3 methods overwritten by 'htmltools':
  method               from         
  print.html           tools:rstudio
  print.shiny.tag      tools:rstudio
  print.shiny.tag.list tools:rstudio
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio

Attaching package: ‘plotly’

The following object is masked from ‘package:ggplot2’:

    last_plot

The following object is masked from ‘package:stats’:

    filter

The following object is masked from ‘package:graphics’:

    layout
library(fable)
Warning: package ‘fable’ was built under R version 4.1.1
Loading required package: fabletools
Warning: package ‘fabletools’ was built under R version 4.1.1
library(tsibble)
Warning: package ‘tsibble’ was built under R version 4.1.1

Attaching package: ‘tsibble’

The following object is masked from ‘package:lubridate’:

    interval

The following objects are masked from ‘package:base’:

    intersect, setdiff, union
library(tsibbledata)
Warning: package ‘tsibbledata’ was built under R version 4.1.1
## ---------------------------------------------------------------------------
#Load all the datafiles into dataset using loop
## ---------------------------------------------------------------------------

## List the files.

setwd("../raw_data")
Warning: The working directory was changed to E:/Prathiba_Course/_codeclan/my_projects/phs_covid/raw_data inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
files <- list.files(pattern=".csv")
## read data using loop
for (f in files) {
  file_name <- str_to_lower(str_replace(f,".csv",""))
  assign(paste(file_name),read_csv(f))
}
Rows: 25620 Columns: 18
-- Column specification -------------------------------------------------------------------------------------------
Delimiter: ","
chr (8): Country, Sex, SexQF, AgeGroup, AgeGroupQF, Dose, PercentCoverageQF, CumulativePercentCoverageQF
dbl (6): Date, Population, NumberVaccinated, PercentCoverage, CumulativeNumberVaccinated, CumulativePercentCove...
lgl (4): PopulationQF, DoseQF, NumberVaccinatedQF, CumulativeNumberVaccinatedQF

i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
Rows: 419070 Columns: 20
-- Column specification -------------------------------------------------------------------------------------------
Delimiter: ","
chr (10): HB, HBQF, HBName, Sex, SexQF, AgeGroup, AgeGroupQF, Dose, PercentCoverageQF, CumulativePercentCoverageQF
dbl  (6): Date, Population, NumberVaccinated, PercentCoverage, CumulativeNumberVaccinated, CumulativePercentCov...
lgl  (4): PopulationQF, DoseQF, NumberVaccinatedQF, CumulativeNumberVaccinatedQF

i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
Rows: 865590 Columns: 20
-- Column specification -------------------------------------------------------------------------------------------
Delimiter: ","
chr (9): CA, CAName, Sex, SexQF, AgeGroup, AgeGroupQF, Dose, PercentCoverageQF, CumulativePercentCoverageQF
dbl (6): Date, Population, NumberVaccinated, PercentCoverage, CumulativeNumberVaccinated, CumulativePercentCove...
lgl (5): CAQF, PopulationQF, DoseQF, NumberVaccinatedQF, CumulativeNumberVaccinatedQF

i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
Rows: 4270 Columns: 10
-- Column specification -------------------------------------------------------------------------------------------
Delimiter: ","
chr (4): Country, Product, Dose, AgeBand
dbl (6): Date, Population, NumberVaccinated, PercentCoverage, CumulativeNumberVaccinated, CumulativePercentCove...

i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
Rows: 32 Columns: 15
-- Column specification -------------------------------------------------------------------------------------------
Delimiter: ","
chr  (2): CA, CAName
dbl (13): Date, TotalTests, TotalTestsNew, PositiveTests, PositiveTestsNew, PositivePercentageTotal, PositivePe...

i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
Rows: 15 Columns: 15
-- Column specification -------------------------------------------------------------------------------------------
Delimiter: ","
chr  (2): HB, HBName
dbl (13): Date, TotalTests, TotalTestsNew, PositiveTests, PositiveTestsNew, PositivePercentageTotal, PositivePe...

i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
Rows: 19403 Columns: 14
-- Column specification -------------------------------------------------------------------------------------------
Delimiter: ","
chr (5): Country, Sex, SexQF, AgeGroup, AgeGroupQF
dbl (9): Date, DailyPositive, CumulativePositive, CrudeRatePositive, DailyDeaths, CumulativeDeaths, CrudeRateDe...

i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
Rows: 18807 Columns: 21
-- Column specification -------------------------------------------------------------------------------------------
Delimiter: ","
chr  (2): CA, CAName
dbl (19): Date, DailyPositive, CumulativePositive, CrudeRatePositive, CrudeRate7DayPositive, DailyDeaths, Cumul...

i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
Rows: 8811 Columns: 25
-- Column specification -------------------------------------------------------------------------------------------
Delimiter: ","
chr  (4): HB, HBName, HospitalAdmissionsQF, ICUAdmissionsQF
dbl (21): Date, DailyPositive, CumulativePositive, CrudeRatePositive, CrudeRate7DayPositive, DailyDeaths, Cumul...

i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
Rows: 658923 Columns: 10
-- Column specification -------------------------------------------------------------------------------------------
Delimiter: ","
chr (7): IntZone, IntZoneName, CA, CAName, Positive7DayQF, CrudeRate7DayPositive, CrudeRate7DayPositiveQF
dbl (3): Date, Positive7Day, Population

i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
Rows: 2940 Columns: 11
-- Column specification -------------------------------------------------------------------------------------------
Delimiter: ","
chr  (1): Country
dbl (10): Date, SIMDQuintile, DailyPositive, CumulativePositive, CrudeRatePositive, DailyDeaths, CumulativeDeat...

i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Function to create a theme for the plot-----------------------------------------
color_theme <- function() {
  theme(
    plot.background = element_rect(fill = "white"),
    plot.title = element_text(size = rel(2)),
    plot.title.position = "plot",
    panel.border = element_rect(colour = "blue", fill = NA, linetype = 1),
    panel.background = element_rect(fill = "white"),
    panel.grid = element_line(colour = "grey85", linetype = 1, size = 0.5),
    axis.text = element_text(colour = "blue", face = "italic", size = 12),
    axis.title.y = element_text(colour = "#1B732B", size = 10, angle = 90),
    axis.title.x = element_text(colour = "#1B732B", size = 10),
    legend.box.background = element_rect(),
    legend.box.margin = margin(6, 6, 6, 6)
  )
}

1) Analyse the Daily trend on positive cases

trend_hb_daily <- trend_hb_20211008 %>% 
  clean_names()
#Convert the date to date format
trend_hb_daily <- trend_hb_daily %>% 
  mutate(date = as_date(ymd(date))) %>% 
  filter (year(date) == 2021)
  #filter(date >="2021-04-01") 

Plot1(a): Trend on people who tested positive (For all the data).

#Plot to visualise trend on positive cases.
x <- trend_hb_daily %>% 
  filter (hb_name == "Scotland") %>% 
  ggplot()+
  aes(x = date, y = daily_positive)+
  geom_line()+
  #scale_x_date(breaks = "1 month")+
  scale_x_date(breaks = "1 month", date_labels = "%b - %y" )+
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1))+
  ggtitle("Trend on Positive cases") +
  xlab("Year") +
  ylab("No of Positive Cases") +
  color_theme()

ggplotly(x)
NA
NA

Plot1(b): Trend on people who tested positive(For Past 6 months).

x <- trend_hb_daily %>% 
  filter(date >="2021-04-01") %>% 
  filter (hb_name == "Scotland") %>% 
  ggplot()+
  aes(x = date, y = daily_positive)+
  geom_line()+
  #scale_x_date(breaks = "1 month")+
  scale_x_date(breaks = "1 month", date_labels = "%b - %y" )+
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1))+
  ggtitle("People tested Positive") +
  xlab("Year") +
  ylab("No of Positive Cases") +
  color_theme()

ggplotly(x)

EXTRA 1: Forecast on Positive cases:

trend <- trend_hb_daily %>% 
  filter (hb_name == "Scotland") %>% 
  filter(date >="2021-06-01") %>% 
  select(date, daily_positive)

trend <- as_tsibble(trend, index = date)

fit <- trend %>%
  model(
    snaive = SNAIVE(daily_positive),
    mean_model = MEAN(daily_positive),
    arima = ARIMA(daily_positive)
  )
forecast_14days <- fit %>%
  fabletools::forecast(h = 14)
forecast_14days
forecast_14days %>%
 #filter(.model == "snaive") %>%
 autoplot(trend, level = NULL) +
  ggtitle("Forecasts for Positive cases for 2 weeks") +
  xlab("Year") +
  ylab("No of Positive Cases") +
  guides(colour = guide_legend(title = "Forecast"))+
  scale_x_date(breaks = "1 month", date_labels = "%B" )+
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1))

forecast_1month <- fit %>%
  fabletools::forecast(h = "1 month")
forecast_1month 
forecast_1month %>%
 #filter(.model == "snaive") %>%
 autoplot(trend, level = NULL) +
  ggtitle("Forecasts for Positive cases for one month") +
  xlab("Year") +
  ylab("No of Positive Cases") +
  guides(colour = guide_legend(title = "Forecast"))+
  scale_x_date(breaks = "1 month", date_labels = "%B" )+
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1))

# check our available years so we know where to put the split in the data

# Now set our training data from 1992 to 2006
train <- trend %>%
  filter_index("2021-01-01" ~ "2021-08-31")

# run the model on the training set 
fit_train <- train %>%
  model(
    mean_model = MEAN(daily_positive),
    arima = ARIMA(daily_positive),
    snaive = SNAIVE(daily_positive)
  )

forecast_test <- fit_train %>% 
  fabletools::forecast(h = 30)
forecast_test %>%
  autoplot(train, level = NULL) +
    autolayer(filter_index(trend, "2021-09-01" ~.), color = "black") +
    ggtitle("Forecasts for positive cases") +
    xlab("Date") + ylab("Daily Positive") +
    guides(colour=guide_legend(title="Forecast"))
Plot variable not specified, automatically selected `.vars = daily_positive`

accuracy_model <- fabletools::accuracy(forecast_test, trend)

accuracy_model %>% 
  select(-.type) %>%
  arrange(RMSE)

2 Analyse the trend on Hospitalisations:

plot_hosp <- trend_hb_daily %>% 
  filter(date >="2021-04-01") %>% 
  filter (hb_name == "Scotland") %>% 
  filter(!(is.na(hospital_admissions))) %>% 
  ggplot()+
  aes(x = date, y = hospital_admissions)+
  geom_col()+
  #scale_x_date(breaks = "1 month")+
  scale_x_date(breaks = "1 week", date_labels = "%d - %b" )+
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1))+
  ggtitle("Trend on Hospitalisations") +
  xlab("Date (months)") +
  ylab("No of patients admitted") +
  color_theme()

ggplotly(plot_hosp)
NA

2 (b) Forecast on Hospitalisation:**

Using 6 months of data ( Two - Wave)

forecast_14days %>%
# filter(.model == "snaive") %>%
 autoplot(trend_hosp, level = NULL) +
  ggtitle("Forecasts for Hospital admissions cases for 2 weeks") +
  xlab("Year") +
  ylab("No of patients admitted") +
  guides(colour = guide_legend(title = "Forecast"))+
  scale_x_date(breaks = "1 month", date_labels = "%B" )+
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1))

NA
NA
NA
NA
forecast_1month <- fit %>%
  fabletools::forecast(h = "1 month")
forecast_1month 
forecast_1month %>%
 filter(.model %in% c("snaive","arima")) %>%
 autoplot(trend_hosp, level = NULL) +
  ggtitle("Forecasts for Hospitalisation for one month") +
  xlab("Year") +
  ylab("No of Positive Cases") +
  guides(colour = guide_legend(title = "Forecast"))+
  scale_x_date(breaks = "1 month", date_labels = "%B" )+
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1))

#  set the training data
train <- trend_hosp %>%
  filter_index("2021-06-01" ~ "2021-08-31")

# run the model on the training set 
fit_train <- train %>%
  model(
    mean_model = MEAN(hospital_admissions),
    arima = ARIMA(hospital_admissions),
    snaive = SNAIVE(hospital_admissions),
    ets = ETS(log(hospital_admissions) ~ error("M") + trend("Ad") + season("A"))
  )

forecast_test <- fit_train %>% 
  fabletools::forecast(h = 35)
forecast_test %>%
  filter(.model %in% c("arima","snaive")) %>%
  autoplot(train ) +
    autolayer(filter_index(trend_hosp, "2021-06-01" ~.), color = "black") +
    ggtitle("Forecasts for Hospitalisations") +
    facet_wrap(~.model)+
    xlab("Date") + 
    ylab("No of Patients admitted") +
    guides(colour=guide_legend(title="Forecast"))
Plot variable not specified, automatically selected `.vars = hospital_admissions`

accuracy_model <- fabletools::accuracy(forecast_test, trend_hosp)
Warning: The future dataset is incomplete, incomplete out-of-sample data will be treated as missing. 
1 observation is missing at 2021-10-05
accuracy_model %>% 
  select(-.type) %>%
  arrange(RMSE)

Prepare the data

daily_vacc_hb <- daily_vacc_hb_20211009 %>% 
  clean_names()
 #Convert the date to date format
daily_vacc_hb <- daily_vacc_hb %>% 
  mutate(date = as_date(ymd(date)))
  #filter (year(date) == 2021)
daily_vacc_hb_plot <- daily_vacc_hb %>% 
  filter(hb_name == "Scotland") %>% 
  filter(sex =="Total") %>% 
  filter(age_group == "All vaccinations") %>% 
  filter(number_vaccinated!=0) 
  #select(date,sex, age_group, number_vaccinated)

Plot3(a): Trend on people who tested positive (For all the data).

#Plot to visualise trend on positive cases.
plot_vaccine <- daily_vacc_hb_plot %>% 
  ggplot()+
  aes(x = date, y = number_vaccinated)+
  geom_line(aes(color = dose))+
  facet_wrap(~dose)+
  #scale_x_date(breaks = "1 month")+
  scale_x_date(breaks = "1 month", date_labels = "%b - %y" )+
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1))+
  ggtitle("Trend on Vaccination") +
  xlab("Year") +
  ylab("No of Positive Cases") +
  color_theme()

ggplotly(plot_vaccine)
LS0tDQp0aXRsZTogIlBIU19Db3ZpZCBBbmFseXNpcyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMjIyAqKkxvYWQgdGhlIGRhdGFzZXRzKioNCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoamFuaXRvcikNCmxpYnJhcnkoaGVyZSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGZhYmxlKQ0KbGlicmFyeSh0c2liYmxlKQ0KbGlicmFyeSh0c2liYmxlZGF0YSkNCmBgYA0KDQpgYGB7cn0NCiMjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KI0xvYWQgYWxsIHRoZSBkYXRhZmlsZXMgaW50byBkYXRhc2V0IHVzaW5nIGxvb3ANCiMjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyBMaXN0IHRoZSBmaWxlcy4NCg0Kc2V0d2QoIi4uL3Jhd19kYXRhIikNCmZpbGVzIDwtIGxpc3QuZmlsZXMocGF0dGVybj0iLmNzdiIpDQojIyByZWFkIGRhdGEgdXNpbmcgbG9vcA0KZm9yIChmIGluIGZpbGVzKSB7DQogIGZpbGVfbmFtZSA8LSBzdHJfdG9fbG93ZXIoc3RyX3JlcGxhY2UoZiwiLmNzdiIsIiIpKQ0KICBhc3NpZ24ocGFzdGUoZmlsZV9uYW1lKSxyZWFkX2NzdihmKSkNCn0NCmBgYA0KDQpgYGB7cn0NCiMgRnVuY3Rpb24gdG8gY3JlYXRlIGEgdGhlbWUgZm9yIHRoZSBwbG90LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCmNvbG9yX3RoZW1lIDwtIGZ1bmN0aW9uKCkgew0KICB0aGVtZSgNCiAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLA0KICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgyKSksDQogICAgcGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwbG90IiwNCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X3JlY3QoY29sb3VyID0gImJsdWUiLCBmaWxsID0gTkEsIGxpbmV0eXBlID0gMSksDQogICAgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiksDQogICAgcGFuZWwuZ3JpZCA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiZ3JleTg1IiwgbGluZXR5cGUgPSAxLCBzaXplID0gMC41KSwNCiAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3VyID0gImJsdWUiLCBmYWNlID0gIml0YWxpYyIsIHNpemUgPSAxMiksDQogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9ICIjMUI3MzJCIiwgc2l6ZSA9IDEwLCBhbmdsZSA9IDkwKSwNCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoY29sb3VyID0gIiMxQjczMkIiLCBzaXplID0gMTApLA0KICAgIGxlZ2VuZC5ib3guYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgpLA0KICAgIGxlZ2VuZC5ib3gubWFyZ2luID0gbWFyZ2luKDYsIDYsIDYsIDYpDQogICkNCn0NCmBgYA0KDQojIyAqKjEpIEFuYWx5c2UgdGhlIERhaWx5IHRyZW5kIG9uIHBvc2l0aXZlIGNhc2VzKioNCg0KYGBge3J9DQp0cmVuZF9oYl9kYWlseSA8LSB0cmVuZF9oYl8yMDIxMTAwOCAlPiUgDQogIGNsZWFuX25hbWVzKCkNCmBgYA0KDQpgYGB7cn0NCiNDb252ZXJ0IHRoZSBkYXRlIHRvIGRhdGUgZm9ybWF0DQp0cmVuZF9oYl9kYWlseSA8LSB0cmVuZF9oYl9kYWlseSAlPiUgDQogIG11dGF0ZShkYXRlID0gYXNfZGF0ZSh5bWQoZGF0ZSkpKSAlPiUgDQogIGZpbHRlciAoeWVhcihkYXRlKSA9PSAyMDIxKQ0KICAjZmlsdGVyKGRhdGUgPj0iMjAyMS0wNC0wMSIpIA0KYGBgDQoNCiMjIyAqKipQbG90MShhKTogVHJlbmQgb24gcGVvcGxlIHdobyB0ZXN0ZWQgcG9zaXRpdmUgKEZvciBhbGwgdGhlIGRhdGEpLioqKg0KDQpgYGB7cn0NCiNQbG90IHRvIHZpc3VhbGlzZSB0cmVuZCBvbiBwb3NpdGl2ZSBjYXNlcy4NCnggPC0gdHJlbmRfaGJfZGFpbHkgJT4lIA0KICBmaWx0ZXIgKGhiX25hbWUgPT0gIlNjb3RsYW5kIikgJT4lIA0KICBnZ3Bsb3QoKSsNCiAgYWVzKHggPSBkYXRlLCB5ID0gZGFpbHlfcG9zaXRpdmUpKw0KICBnZW9tX2xpbmUoKSsNCiAgI3NjYWxlX3hfZGF0ZShicmVha3MgPSAiMSBtb250aCIpKw0KICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiAtICV5IiApKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCB2anVzdCA9IDEsIGhqdXN0PTEpKSsNCiAgZ2d0aXRsZSgiVHJlbmQgb24gUG9zaXRpdmUgY2FzZXMiKSArDQogIHhsYWIoIlllYXIiKSArDQogIHlsYWIoIk5vIG9mIFBvc2l0aXZlIENhc2VzIikgKw0KICBjb2xvcl90aGVtZSgpDQoNCmdncGxvdGx5KHgpDQoNCg0KYGBgDQoNCiMjIyAqKipQbG90MShiKTogVHJlbmQgb24gcGVvcGxlIHdobyB0ZXN0ZWQgcG9zaXRpdmUoRm9yIFBhc3QgNiBtb250aHMpLioqKg0KDQpgYGB7cn0NCnggPC0gdHJlbmRfaGJfZGFpbHkgJT4lIA0KICBmaWx0ZXIoZGF0ZSA+PSIyMDIxLTA0LTAxIikgJT4lIA0KICBmaWx0ZXIgKGhiX25hbWUgPT0gIlNjb3RsYW5kIikgJT4lIA0KICBnZ3Bsb3QoKSsNCiAgYWVzKHggPSBkYXRlLCB5ID0gZGFpbHlfcG9zaXRpdmUpKw0KICBnZW9tX2xpbmUoKSsNCiAgI3NjYWxlX3hfZGF0ZShicmVha3MgPSAiMSBtb250aCIpKw0KICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlYiAtICV5IiApKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCB2anVzdCA9IDEsIGhqdXN0PTEpKSsNCiAgZ2d0aXRsZSgiUGVvcGxlIHRlc3RlZCBQb3NpdGl2ZSIpICsNCiAgeGxhYigiWWVhciIpICsNCiAgeWxhYigiTm8gb2YgUG9zaXRpdmUgQ2FzZXMiKSArDQogIGNvbG9yX3RoZW1lKCkNCg0KZ2dwbG90bHkoeCkNCmBgYA0KDQojIyAqKkVYVFJBIDE6IEZvcmVjYXN0IG9uIFBvc2l0aXZlIGNhc2VzOioqDQoNCmBgYHtyfQ0KdHJlbmQgPC0gdHJlbmRfaGJfZGFpbHkgJT4lIA0KICBmaWx0ZXIgKGhiX25hbWUgPT0gIlNjb3RsYW5kIikgJT4lIA0KICBmaWx0ZXIoZGF0ZSA+PSIyMDIxLTA2LTAxIikgJT4lIA0KICBzZWxlY3QoZGF0ZSwgZGFpbHlfcG9zaXRpdmUpDQoNCnRyZW5kIDwtIGFzX3RzaWJibGUodHJlbmQsIGluZGV4ID0gZGF0ZSkNCg0KZml0IDwtIHRyZW5kICU+JQ0KICBtb2RlbCgNCiAgICBzbmFpdmUgPSBTTkFJVkUoZGFpbHlfcG9zaXRpdmUpLA0KICAgIG1lYW5fbW9kZWwgPSBNRUFOKGRhaWx5X3Bvc2l0aXZlKSwNCiAgICBhcmltYSA9IEFSSU1BKGRhaWx5X3Bvc2l0aXZlKQ0KICApDQpmb3JlY2FzdF8xNGRheXMgPC0gZml0ICU+JQ0KICBmYWJsZXRvb2xzOjpmb3JlY2FzdChoID0gMTQpDQpmb3JlY2FzdF8xNGRheXMNCmBgYA0KDQpgYGB7cn0NCmZvcmVjYXN0XzE0ZGF5cyAlPiUNCiAjZmlsdGVyKC5tb2RlbCA9PSAic25haXZlIikgJT4lDQogYXV0b3Bsb3QodHJlbmQsIGxldmVsID0gTlVMTCkgKw0KICBnZ3RpdGxlKCJGb3JlY2FzdHMgZm9yIFBvc2l0aXZlIGNhc2VzIGZvciAyIHdlZWtzIikgKw0KICB4bGFiKCJZZWFyIikgKw0KICB5bGFiKCJObyBvZiBQb3NpdGl2ZSBDYXNlcyIpICsNCiAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZCh0aXRsZSA9ICJGb3JlY2FzdCIpKSsNCiAgc2NhbGVfeF9kYXRlKGJyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJUIiICkrDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIHZqdXN0ID0gMSwgaGp1c3Q9MSkpDQpgYGANCg0KYGBge3J9DQpmb3JlY2FzdF8xbW9udGggPC0gZml0ICU+JQ0KICBmYWJsZXRvb2xzOjpmb3JlY2FzdChoID0gIjEgbW9udGgiKQ0KZm9yZWNhc3RfMW1vbnRoIA0KYGBgDQoNCmBgYHtyfQ0KZm9yZWNhc3RfMW1vbnRoICU+JQ0KICNmaWx0ZXIoLm1vZGVsID09ICJzbmFpdmUiKSAlPiUNCiBhdXRvcGxvdCh0cmVuZCwgbGV2ZWwgPSBOVUxMKSArDQogIGdndGl0bGUoIkZvcmVjYXN0cyBmb3IgUG9zaXRpdmUgY2FzZXMgZm9yIG9uZSBtb250aCIpICsNCiAgeGxhYigiWWVhciIpICsNCiAgeWxhYigiTm8gb2YgUG9zaXRpdmUgQ2FzZXMiKSArDQogIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQodGl0bGUgPSAiRm9yZWNhc3QiKSkrDQogIHNjYWxlX3hfZGF0ZShicmVha3MgPSAiMSBtb250aCIsIGRhdGVfbGFiZWxzID0gIiVCIiApKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCB2anVzdCA9IDEsIGhqdXN0PTEpKQ0KDQpgYGANCmBgYHtyfQ0KIyBjaGVjayBvdXIgYXZhaWxhYmxlIHllYXJzIHNvIHdlIGtub3cgd2hlcmUgdG8gcHV0IHRoZSBzcGxpdCBpbiB0aGUgZGF0YQ0KDQojIE5vdyBzZXQgb3VyIHRyYWluaW5nIGRhdGEgZnJvbSAxOTkyIHRvIDIwMDYNCnRyYWluIDwtIHRyZW5kICU+JQ0KICBmaWx0ZXJfaW5kZXgoIjIwMjEtMDEtMDEiIH4gIjIwMjEtMDgtMzEiKQ0KDQojIHJ1biB0aGUgbW9kZWwgb24gdGhlIHRyYWluaW5nIHNldCANCmZpdF90cmFpbiA8LSB0cmFpbiAlPiUNCiAgbW9kZWwoDQogICAgbWVhbl9tb2RlbCA9IE1FQU4oZGFpbHlfcG9zaXRpdmUpLA0KICAgIGFyaW1hID0gQVJJTUEoZGFpbHlfcG9zaXRpdmUpLA0KICAgIHNuYWl2ZSA9IFNOQUlWRShkYWlseV9wb3NpdGl2ZSkNCiAgKQ0KDQpmb3JlY2FzdF90ZXN0IDwtIGZpdF90cmFpbiAlPiUgDQogIGZhYmxldG9vbHM6OmZvcmVjYXN0KGggPSAzMCkNCg0KYGBgDQoNCmBgYHtyfQ0KZm9yZWNhc3RfdGVzdCAlPiUNCiAgYXV0b3Bsb3QodHJhaW4sIGxldmVsID0gTlVMTCkgKw0KICAgIGF1dG9sYXllcihmaWx0ZXJfaW5kZXgodHJlbmQsICIyMDIxLTA5LTAxIiB+LiksIGNvbG9yID0gImJsYWNrIikgKw0KICAgIGdndGl0bGUoIkZvcmVjYXN0cyBmb3IgcG9zaXRpdmUgY2FzZXMiKSArDQogICAgeGxhYigiRGF0ZSIpICsgeWxhYigiRGFpbHkgUG9zaXRpdmUiKSArDQogICAgZ3VpZGVzKGNvbG91cj1ndWlkZV9sZWdlbmQodGl0bGU9IkZvcmVjYXN0IikpDQpgYGANCg0KDQpgYGB7cn0NCmFjY3VyYWN5X21vZGVsIDwtIGZhYmxldG9vbHM6OmFjY3VyYWN5KGZvcmVjYXN0X3Rlc3QsIHRyZW5kKQ0KDQphY2N1cmFjeV9tb2RlbCAlPiUgDQogIHNlbGVjdCgtLnR5cGUpICU+JQ0KICBhcnJhbmdlKFJNU0UpDQpgYGANCg0KDQojIyAqKjIgQW5hbHlzZSB0aGUgdHJlbmQgb24gSG9zcGl0YWxpc2F0aW9uczoqKg0KDQpgYGB7cn0NCnBsb3RfaG9zcCA8LSB0cmVuZF9oYl9kYWlseSAlPiUgDQogIGZpbHRlcihkYXRlID49IjIwMjEtMDQtMDEiKSAlPiUgDQogIGZpbHRlciAoaGJfbmFtZSA9PSAiU2NvdGxhbmQiKSAlPiUgDQogIGZpbHRlcighKGlzLm5hKGhvc3BpdGFsX2FkbWlzc2lvbnMpKSkgJT4lIA0KICBnZ3Bsb3QoKSsNCiAgYWVzKHggPSBkYXRlLCB5ID0gaG9zcGl0YWxfYWRtaXNzaW9ucykrDQogIGdlb21fY29sKCkrDQogICNzY2FsZV94X2RhdGUoYnJlYWtzID0gIjEgbW9udGgiKSsNCiAgc2NhbGVfeF9kYXRlKGJyZWFrcyA9ICIxIHdlZWsiLCBkYXRlX2xhYmVscyA9ICIlZCAtICViIiApKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCB2anVzdCA9IDEsIGhqdXN0PTEpKSsNCiAgZ2d0aXRsZSgiVHJlbmQgb24gSG9zcGl0YWxpc2F0aW9ucyIpICsNCiAgeGxhYigiRGF0ZSAobW9udGhzKSIpICsNCiAgeWxhYigiTm8gb2YgcGF0aWVudHMgYWRtaXR0ZWQiKSArDQogIGNvbG9yX3RoZW1lKCkNCg0KZ2dwbG90bHkocGxvdF9ob3NwKQ0KDQpgYGANCg0KDQojIyAyIChiKSBGb3JlY2FzdCBvbiBIb3NwaXRhbGlzYXRpb246KioNCg0KVXNpbmcgNiBtb250aHMgb2YgZGF0YSAoIFR3byAtIFdhdmUpDQoNCmBgYHtyfQ0KdHJlbmRfaG9zcCA8LSB0cmVuZF9oYl9kYWlseSAlPiUgDQogIGZpbHRlciAoaGJfbmFtZSA9PSAiU2NvdGxhbmQiKSAlPiUgDQogIGZpbHRlcihkYXRlID49IjIwMjEtMDYtMDEiKSAlPiUgDQogIGZpbHRlcighKGlzLm5hKGhvc3BpdGFsX2FkbWlzc2lvbnMpKSkgJT4lIA0KICBzZWxlY3QoZGF0ZSwgaG9zcGl0YWxfYWRtaXNzaW9ucykNCg0KdHJlbmRfaG9zcCA8LSBhc190c2liYmxlKHRyZW5kX2hvc3AsIGluZGV4ID0gZGF0ZSkNCg0KZml0IDwtIHRyZW5kX2hvc3AgJT4lDQogIG1vZGVsKA0KICAgIHNuYWl2ZSA9IFNOQUlWRShob3NwaXRhbF9hZG1pc3Npb25zKSwNCiAgICBtZWFuX21vZGVsID0gTUVBTihob3NwaXRhbF9hZG1pc3Npb25zKSwNCiAgICBhcmltYSA9IEFSSU1BKGhvc3BpdGFsX2FkbWlzc2lvbnMpLA0KICAgIGV0cyA9IEVUUyhsb2coaG9zcGl0YWxfYWRtaXNzaW9ucykgfiBlcnJvcigiTSIpICsgdHJlbmQoIkFkIikgKyBzZWFzb24oIkEiKSkNCiAgKQ0KZm9yZWNhc3RfMTRkYXlzIDwtIGZpdCAlPiUNCiAgZmFibGV0b29sczo6Zm9yZWNhc3QoaCA9IDE0KQ0KZm9yZWNhc3RfMTRkYXlzDQpgYGANCg0KYGBge3J9DQpmb3JlY2FzdF8xNGRheXMgJT4lDQojIGZpbHRlcigubW9kZWwgPT0gInNuYWl2ZSIpICU+JQ0KIGF1dG9wbG90KHRyZW5kX2hvc3AsIGxldmVsID0gTlVMTCkgKw0KICBnZ3RpdGxlKCJGb3JlY2FzdHMgZm9yIEhvc3BpdGFsIGFkbWlzc2lvbnMgY2FzZXMgZm9yIDIgd2Vla3MiKSArDQogIHhsYWIoIlllYXIiKSArDQogIHlsYWIoIk5vIG9mIHBhdGllbnRzIGFkbWl0dGVkIikgKw0KICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkZvcmVjYXN0IikpKw0KICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlQiIgKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgdmp1c3QgPSAxLCBoanVzdD0xKSkNCg0KDQoNCg0KYGBgDQoNCmBgYHtyfQ0KZm9yZWNhc3RfMW1vbnRoIDwtIGZpdCAlPiUNCiAgZmFibGV0b29sczo6Zm9yZWNhc3QoaCA9ICIxIG1vbnRoIikNCmZvcmVjYXN0XzFtb250aCANCmBgYA0KDQpgYGB7cn0NCmZvcmVjYXN0XzFtb250aCAlPiUNCiBmaWx0ZXIoLm1vZGVsICVpbiUgYygic25haXZlIiwiYXJpbWEiKSkgJT4lDQogYXV0b3Bsb3QodHJlbmRfaG9zcCwgbGV2ZWwgPSBOVUxMKSArDQogIGdndGl0bGUoIkZvcmVjYXN0cyBmb3IgSG9zcGl0YWxpc2F0aW9uIGZvciBvbmUgbW9udGgiKSArDQogIHhsYWIoIlllYXIiKSArDQogIHlsYWIoIk5vIG9mIFBvc2l0aXZlIENhc2VzIikgKw0KICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkZvcmVjYXN0IikpKw0KICBzY2FsZV94X2RhdGUoYnJlYWtzID0gIjEgbW9udGgiLCBkYXRlX2xhYmVscyA9ICIlQiIgKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgdmp1c3QgPSAxLCBoanVzdD0xKSkNCg0KYGBgDQpgYGB7cn0NCiMgIHNldCB0aGUgdHJhaW5pbmcgZGF0YQ0KdHJhaW4gPC0gdHJlbmRfaG9zcCAlPiUNCiAgZmlsdGVyX2luZGV4KCIyMDIxLTA2LTAxIiB+ICIyMDIxLTA4LTMxIikNCg0KIyBydW4gdGhlIG1vZGVsIG9uIHRoZSB0cmFpbmluZyBzZXQgDQpmaXRfdHJhaW4gPC0gdHJhaW4gJT4lDQogIG1vZGVsKA0KICAgIG1lYW5fbW9kZWwgPSBNRUFOKGhvc3BpdGFsX2FkbWlzc2lvbnMpLA0KICAgIGFyaW1hID0gQVJJTUEoaG9zcGl0YWxfYWRtaXNzaW9ucyksDQogICAgc25haXZlID0gU05BSVZFKGhvc3BpdGFsX2FkbWlzc2lvbnMpLA0KICAgIGV0cyA9IEVUUyhsb2coaG9zcGl0YWxfYWRtaXNzaW9ucykgfiBlcnJvcigiTSIpICsgdHJlbmQoIkFkIikgKyBzZWFzb24oIkEiKSkNCiAgKQ0KDQpmb3JlY2FzdF90ZXN0IDwtIGZpdF90cmFpbiAlPiUgDQogIGZhYmxldG9vbHM6OmZvcmVjYXN0KGggPSAzNSkNCg0KYGBgDQoNCmBgYHtyfQ0KZm9yZWNhc3RfdGVzdCAlPiUNCiAgZmlsdGVyKC5tb2RlbCAlaW4lIGMoImFyaW1hIiwic25haXZlIikpICU+JQ0KICBhdXRvcGxvdCh0cmFpbiApICsNCiAgICBhdXRvbGF5ZXIoZmlsdGVyX2luZGV4KHRyZW5kX2hvc3AsICIyMDIxLTA2LTAxIiB+LiksIGNvbG9yID0gImJsYWNrIikgKw0KICAgIGdndGl0bGUoIkZvcmVjYXN0cyBmb3IgSG9zcGl0YWxpc2F0aW9ucyIpICsNCiAgICBmYWNldF93cmFwKH4ubW9kZWwpKw0KICAgIHhsYWIoIkRhdGUiKSArIA0KICAgIHlsYWIoIk5vIG9mIFBhdGllbnRzIGFkbWl0dGVkIikgKw0KICAgIGd1aWRlcyhjb2xvdXI9Z3VpZGVfbGVnZW5kKHRpdGxlPSJGb3JlY2FzdCIpKQ0KYGBgDQoNCg0KYGBge3J9DQphY2N1cmFjeV9tb2RlbCA8LSBmYWJsZXRvb2xzOjphY2N1cmFjeShmb3JlY2FzdF90ZXN0LCB0cmVuZF9ob3NwKQ0KDQphY2N1cmFjeV9tb2RlbCAlPiUgDQogIHNlbGVjdCgtLnR5cGUpICU+JQ0KICBhcnJhbmdlKFJNU0UpDQpgYGANCg0KUHJlcGFyZSB0aGUgZGF0YQ0KYGBge3J9DQpkYWlseV92YWNjX2hiIDwtIGRhaWx5X3ZhY2NfaGJfMjAyMTEwMDkgJT4lIA0KICBjbGVhbl9uYW1lcygpDQpgYGANCg0KYGBge3J9DQogI0NvbnZlcnQgdGhlIGRhdGUgdG8gZGF0ZSBmb3JtYXQNCmRhaWx5X3ZhY2NfaGIgPC0gZGFpbHlfdmFjY19oYiAlPiUgDQogIG11dGF0ZShkYXRlID0gYXNfZGF0ZSh5bWQoZGF0ZSkpKQ0KICAjZmlsdGVyICh5ZWFyKGRhdGUpID09IDIwMjEpDQpgYGANCmBgYHtyfQ0KZGFpbHlfdmFjY19oYl9wbG90IDwtIGRhaWx5X3ZhY2NfaGIgJT4lIA0KICBmaWx0ZXIoaGJfbmFtZSA9PSAiU2NvdGxhbmQiKSAlPiUgDQogIGZpbHRlcihzZXggPT0iVG90YWwiKSAlPiUgDQogIGZpbHRlcihhZ2VfZ3JvdXAgPT0gIkFsbCB2YWNjaW5hdGlvbnMiKSAlPiUgDQogIGZpbHRlcihudW1iZXJfdmFjY2luYXRlZCE9MCkgDQogICNzZWxlY3QoZGF0ZSxzZXgsIGFnZV9ncm91cCwgbnVtYmVyX3ZhY2NpbmF0ZWQpDQpgYGANCg0KDQojIyMgKioqUGxvdDMoYSk6IFRyZW5kIG9uIHBlb3BsZSB3aG8gdGVzdGVkIHBvc2l0aXZlIChGb3IgYWxsIHRoZSBkYXRhKS4qKioNCg0KYGBge3J9DQojUGxvdCB0byB2aXN1YWxpc2UgdHJlbmQgb24gcG9zaXRpdmUgY2FzZXMuDQpwbG90X3ZhY2NpbmUgPC0gZGFpbHlfdmFjY19oYl9wbG90ICU+JSANCiAgZ2dwbG90KCkrDQogIGFlcyh4ID0gZGF0ZSwgeSA9IG51bWJlcl92YWNjaW5hdGVkKSsNCiAgZ2VvbV9saW5lKGFlcyhjb2xvciA9IGRvc2UpKSsNCiAgZmFjZXRfd3JhcCh+ZG9zZSkrDQogICNzY2FsZV94X2RhdGUoYnJlYWtzID0gIjEgbW9udGgiKSsNCiAgc2NhbGVfeF9kYXRlKGJyZWFrcyA9ICIxIG1vbnRoIiwgZGF0ZV9sYWJlbHMgPSAiJWIgLSAleSIgKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgdmp1c3QgPSAxLCBoanVzdD0xKSkrDQogIGdndGl0bGUoIlRyZW5kIG9uIFZhY2NpbmF0aW9uIikgKw0KICB4bGFiKCJZZWFyIikgKw0KICB5bGFiKCJObyBvZiBQb3NpdGl2ZSBDYXNlcyIpICsNCiAgY29sb3JfdGhlbWUoKQ0KDQpnZ3Bsb3RseShwbG90X3ZhY2NpbmUpDQpgYGANCg0KDQoNCg==